package by.bsu.scs.db.dao;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;
import org.hibernate.HibernateException;
import org.hibernate.LockMode;
import org.hibernate.Session;
import org.hibernate.Transaction;

import by.bsu.scs.model.Discipline;
import by.bsu.scs.model.DisciplineInstructor;
import by.bsu.scs.model.User;
import by.bsu.scs.util.db.HibernateUtil;
import by.bsu.scs.util.manager.PropertyManager;

public class DisciplineInstructorHome {
	private static final String GET_DISCIPLINE_BY_INSTRUCTOR_ID = "getDisciplineByInstructorId";
	private static final String INSTRUCTOR_ID = "instructorId";
	
private static final Logger LOGGER = Logger.getLogger(DisciplineInstructorHome.class);
	
	private Session session = null;
	private Transaction transaction = null;

	public void persist(DisciplineInstructor transientInstance) {
		LOGGER.info("persisting DisciplineInstructor instance");
		session = HibernateUtil.openCurrentSession();
		try {
			transaction = session.beginTransaction();
			session.save(transientInstance);
			transaction.commit();
			LOGGER.info("persist successful");
		} catch (HibernateException e) {
            transaction.rollback();
            LOGGER.error("persist failed", e.getCause());
        }
	}

	public void attachDirty(DisciplineInstructor instance) {
		LOGGER.info("attaching dirty DisciplineInstructor instance");
		session = HibernateUtil.openCurrentSession();
		try {
			transaction = session.beginTransaction();
			session.saveOrUpdate(instance);
			transaction.commit();
			LOGGER.info("attach successful");
		} catch (HibernateException e) {
            transaction.rollback();
            LOGGER.error("attach failed", e.getCause());
        }
	}

	@SuppressWarnings("deprecation")
	public void attachClean(DisciplineInstructor instance) {
		LOGGER.info("attaching clean DisciplineInstructor instance");
		session = HibernateUtil.openCurrentSession();
		try {
			transaction = session.beginTransaction();
			session.lock(instance, LockMode.NONE);
			transaction.commit();
			LOGGER.info("attach successful");
		} catch (HibernateException e) {
            transaction.rollback();
            LOGGER.error("attach failed", e.getCause());
        }
	}

	public void delete(DisciplineInstructor persistentInstance) {
		LOGGER.info("deleting DisciplineInstructor instance");
		session = HibernateUtil.openCurrentSession();
		try {
			transaction = session.beginTransaction();
			session.delete(persistentInstance);
			transaction.commit();
			LOGGER.info("delete successful");
		} catch (HibernateException e) {
            transaction.rollback();
            LOGGER.error("delete failed", e.getCause());
        }
	}

	public DisciplineInstructor merge(DisciplineInstructor detachedInstance) {
		LOGGER.info("merging Discipline instance");
		session = HibernateUtil.openCurrentSession();
		try {
			transaction = session.beginTransaction();
			DisciplineInstructor result = (DisciplineInstructor) session.merge(detachedInstance);
			transaction.commit();
			LOGGER.info("merge successful");
			return result;
		} catch (HibernateException e) {
            transaction.rollback();
            LOGGER.error("merge failed", e.getCause());
            return null;
        }
	}

	public DisciplineInstructor findById(int id) {
		LOGGER.info("getting DisciplineInstructor instance with id: " + id);
		session = HibernateUtil.openCurrentSession();
		try {
			transaction = session.beginTransaction();
			DisciplineInstructor instance = (DisciplineInstructor) session.get(
					"by.bsu.scs.model.DisciplineInstructor", id);
			if (instance == null) {
				LOGGER.info("get successful, no instance found");
			} else {
				LOGGER.info("get successful, instance found");
			}
			transaction.commit();
			return instance;
		} catch (RuntimeException e) {
			transaction.rollback();
			LOGGER.error("get failed", e.getCause());
			return null;
		}
	}

//	@SuppressWarnings("rawtypes")
//	public List findByExample(DisciplineInstructor instance) {
//		LOGGER.info("finding DisciplineInstructor instance by example");
//		session = HibernateUtil.openCurrentSession();
//		try {
//			transaction = session.beginTransaction();
//			Example example = Example.create(instance).excludeZeroes();
//			List results = session.createCriteria("by.bsu.scs.model.DisciplineInstructor")
//					.add(example).list();
//			LOGGER.info("find by example successful, result size: "
//					+ results.size());
//			transaction.commit();
//			return results;
//		} catch (RuntimeException e) {
//			transaction.rollback();
//			LOGGER.error("find by example failed", e.getCause());
//			return null;
//		}
//	}
// ***************** Manually created methods ******************
	
	@SuppressWarnings("unchecked")
	public List<Discipline> getDisciplineByInstructor(User instructor) {
		Session session = HibernateUtil.openCurrentSession();
		Transaction transaction = null;
		List<Discipline> disciplineList = null;
		try {
			transaction = session.beginTransaction();
			disciplineList = session.getNamedQuery(GET_DISCIPLINE_BY_INSTRUCTOR_ID)
			.setInteger(INSTRUCTOR_ID, instructor.getUserId()).list();
			transaction.commit();
			LOGGER.info("find successful");
		} catch (HibernateException e) {
			if (transaction != null) {
				transaction.rollback();
			}
			LOGGER.error("find failed", e.getCause());
		}
		return disciplineList;
	}
	
	public List<DisciplineInstructor> getDisciplineInstructorByStudentIdSQL(User student) {
		LOGGER.info("finding disciplineInstructor by student id");
		session = HibernateUtil.openCurrentSession();
		try {
			transaction = session.beginTransaction();

			String sql = PropertyManager.getInstance().getProperty(
					PropertyManager.DISCIPLINE_INSTRUCTOR_BY_STUDENT_ID);
			Object[] params = { student.getUserId() };
			MessageFormat messageToFormat = new MessageFormat(sql);
			sql = messageToFormat.format(params);

			List results = session.createSQLQuery(sql).list();

			LOGGER.info("find successful, result size: " + results.size());
			transaction.commit();
			return parseDisciplineInstructorData(results);
		} catch (RuntimeException e) {
			transaction.rollback();
			LOGGER.error("finding disciplineInstructor by student id failed", e.getCause());
			return null;
		}
	}
	
	private List<DisciplineInstructor> parseDisciplineInstructorData(List results) {
		List<DisciplineInstructor> disciplineInstructorList = new ArrayList<DisciplineInstructor>();
		for (Object o : results) {
			Object[] disciplineInstructorData = (Object[]) o;
			DisciplineInstructor disciplineInstructor = new DisciplineInstructor();
			disciplineInstructor.setDisciplineInstructorId((Integer)disciplineInstructorData[0]);
			disciplineInstructor.setDiscipline((new DisciplineHome()).findById((Integer)disciplineInstructorData[1]));
			disciplineInstructor.setInstructor((new UserHome()).findById((Integer)disciplineInstructorData[2]));
			disciplineInstructorList.add(disciplineInstructor);
		}
		return disciplineInstructorList;
	}
}
